package com.lengyu.iottransfer.gateway.udp;

import com.alibaba.fastjson.JSONObject;
import com.lengyu.iottransfer.gateway.common.ByteUtils;
import com.lengyu.iottransfer.gateway.config.MqttSendGateway;
import com.lengyu.iottransfer.gateway.dto.MqttDeviceCurrentDto;
import com.lengyu.iottransfer.gateway.redis.RedisUtils;
import com.lengyu.iottransfer.gateway.service.IDeviceTransferService;
import io.lettuce.core.StrAlgoArgs;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetSocketAddress;

@Component
public class UdpServerHandlerForZhongYi extends SimpleChannelInboundHandler<DatagramPacket> {
    private final static Logger logger = LoggerFactory.getLogger(UdpServerHandlerForZhongYi.class);

    @Resource
    private MqttSendGateway mqttSendGateway;

    @Autowired
    IDeviceTransferService deviceTransferService;

    public static UdpServerHandlerForZhongYi udpServerHandler;

    @Autowired
    private RedisUtils redisUtils;

    @PostConstruct
    public void init(){
        udpServerHandler = this;
    }


    private static int IMEI_BYTE_COUNT = 8;

    private static String DEVICE_TYPE="ZHONGYI_NB_WATER_METER";
    private static String DEVICE_CODE_PREFIX = "zywm";

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
        InetSocketAddress sender = datagramPacket.sender();
        String ip = sender.getAddress().getHostAddress();
        ByteBuf buf = datagramPacket.content().copy();
        try {
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            String hexStr = ByteUtils.byteArrayToHexString(data);

            logger.info("收到IP：{},发送的数据：{}", ip, hexStr);
            logger.info("收到IP：{},发送的数据：{}", ip, data);
            String imei = ByteUtils.byteArrayToHexString(data,0,IMEI_BYTE_COUNT,false).toLowerCase();
            logger.info("设备IMEI:" + imei);
            int commandCode = ByteUtils.byteToInt(data[IMEI_BYTE_COUNT]);

            switch (commandCode){
                case 0:
                    //ACK ERROR
                    logger.info("应答错误：" + hexStr);
                    //TODO 发送报警信息或者命令反馈到物联网平台
                    break;
                case 1:
                    //ACK OK
                    logger.info("应答正常：" + hexStr);
                    //TODO 发送命令反馈到物联网平台
                    break;
                case 2:
                    //上报设备状态和流量信息
                    decodeCommand02(data);
                    break;
                case 3:
                    //根据小时上报历史流量
                    logger.info("上报历史流量");
                    break;
                case 6:
                    //reporting  cycle、
                    logger.info("reporting  cycle");
                    break;
                case 7:
                    //上报时间
                    logger.info("上报时间");
                    break;
                case 8:
                    //上报电池电量
                    logger.info("上报电池电量");
                    break;
                case 9:
                    //上报设备状态信息
                    logger.info("上报设备状态信息");
                    break;
                case 10:
                    //上报设备报警信息
                    logger.info("上报设备报警信息");
                    break;
                case 11:
                    //上报固件版本
                    logger.info("上报固件版本");
                    break;
                case 13:
                    //上报温度
                    logger.info("上报温度");
                    break;
                case 14:
                    //上报当前时间
                    logger.info("上报当前时间");
                    break;
                case 224:
                    //上报脉冲系数
                    logger.info("上报脉冲系数");
                    break;
                case 225:
                    //上报系统配置信息
                    logger.info("上报系统配置信息");
                    break;
                case 255:
                    //timeout
                    logger.info("timeout");
                    break;
                default:
                    logger.info("未知设备消息");
            }
//            // 下面进行业务代码处理
//            if(commandCode == 0){
//
//            }
//
//            else if(hexStr.startsWith("06")){
//                //reporting  cycle、
//                logger.info("reporting  cycle");
//            }
//            else if(hexStr.startsWith("07")){
//                //上报时间
//                logger.info("上报时间");
//            }
//            else if(hexStr.startsWith("08")){
//                //上报电池电量
//                logger.info("上报电池电量");
//            }
//            else if(hexStr.startsWith("09")){
//                //上报设备状态信息
//                logger.info("上报设备状态信息");
//            }
//            else if(hexStr.startsWith("0a")){
//                //上报设备报警信息
//                logger.info("上报设备报警信息");
//            }
//            else if(hexStr.startsWith("0b")){
//                //上报固件版本
//                logger.info("上报固件版本");
//            }
//            else if(hexStr.startsWith("0d")){
//                //上报温度
//                logger.info("上报温度");
//            }
//            else if(hexStr.startsWith("0e")){
//                //上报当前时间
//                logger.info("上报当前时间");
//            }
//            else if(hexStr.startsWith("e0")){
//                //上报脉冲系数
//                logger.info("上报脉冲系数");
//            }
//            else if(hexStr.startsWith("e1")){
//                //上报系统配置信息
//                logger.info("上报系统配置信息");
//            }
//            else if(hexStr.startsWith("ff")){
//                //timeout
//            }
//


        }catch (Exception e){
            e.printStackTrace();
        }
        buf.release();
        // TCP返回数据写法
        //channelHandlerContext.channel().writeAndFlush("1");
        // UDP返回数据写法

    }

    public void decodeCommand02(byte[] data){
        String hexStr = ByteUtils.byteArrayToHexString(data);
        String imei = ByteUtils.byteArrayToHexString(data,0,IMEI_BYTE_COUNT,false).toLowerCase();
        int flowData = 0;
        int bv = 0;
        if(data.length == 12 + IMEI_BYTE_COUNT){
            logger.info("大表协议");
            //上报计算流量 及设备状态
            // 流量
            flowData = ByteUtils.byteArrayToIntReverse(data,1+ IMEI_BYTE_COUNT,4);
            logger.info("流量值：" + flowData);

            // 设备状态 D7~D0   D7~D3保留  D2:电池电量 0：正常   1：欠压. D1D0: 00-在线  01：离线  11：不正常
            byte statusByte = data[4+ IMEI_BYTE_COUNT];
            int battery = ByteUtils.getBitValueInByte(2,statusByte);
            logger.info("电池是否正常：" + battery);
            int d1 = ByteUtils.getBitValueInByte(1,statusByte);
            int d0 = ByteUtils.getBitValueInByte(0,statusByte);

            String deviceStatusStr = "";
            if(d1 == 1 && d0 == 1){
                deviceStatusStr = "异常";
            }
            else if(d1 == 0 && d0 == 0){
                deviceStatusStr = "在线";
            }
            else if(d1 == 0 && d0 == 1){
                deviceStatusStr = "离线";
            }
            logger.info("设备状态：" + deviceStatusStr);
            //设备报警  D7~D0：00000000;
            // D7/D6 reservations;
            // D5： measurement Hall fault alarm 0-normal 1-alarm;
            // D4： standby switch alarm 0-normal 1-alarm;
            // D3： strong magnetic interference alarm 0-normal 1-alarm;
            // D2： valve fault alarm 0-normal 1-alarm;
            // D1： reservations;
            // D0： battery power alarm 0-normal 1-alarm.
            byte alarmByte = data[6+ IMEI_BYTE_COUNT];
            if(ByteUtils.getBitValueInByte(5,alarmByte) == 1){
                logger.info("测量霍尔故障");
            }
            else{
                logger.info("测量霍尔正常");
            }

            if(ByteUtils.getBitValueInByte(4,alarmByte) == 1){
                logger.info("备用开关故障");
            }
            else{
                logger.info("备用开关正常");
            }

            if(ByteUtils.getBitValueInByte(3,alarmByte) == 1){
                logger.info("强磁干扰报警");
            }
            else{
                logger.info("强磁干扰正常");
            }

            if(ByteUtils.getBitValueInByte(2,alarmByte) == 1){
                logger.info("阀门故障报警");
            }
            else{
                logger.info("阀门正常");
            }

            if(ByteUtils.getBitValueInByte(2,alarmByte) == 1){
                logger.info("电池电量报警");
            }
            else{
                logger.info("电池电量正常");
            }
            //Battery voltage  电池电压;
            bv = ByteUtils.byteArrayToShortReverse(data,7+ IMEI_BYTE_COUNT);
            if(bv == 0 ) {
                logger.info("电池电压：0 V" );
            }
            else{
                logger.info("电池电压：" + new BigDecimal(bv).divide(new BigDecimal(100),2,RoundingMode.HALF_UP));
            }
            //rssi  信号强度;
            int rssi = ByteUtils.byteToInt(data[9+ IMEI_BYTE_COUNT]);
            logger.info("信号强度：" + rssi);
            //SNR 信噪比
            int snr = ByteUtils.byteToInt(data[10+ IMEI_BYTE_COUNT]);
            logger.info("信号比：" + snr);
        }
        else if(data.length == 20 + IMEI_BYTE_COUNT){
            logger.info("小表协议");
            // 流量
            int zhengflowData = ByteUtils.byteArrayToIntReverse(data,5+ IMEI_BYTE_COUNT,4);
            logger.info("正向流量值：" + zhengflowData);

            // 流量
            int fanflowData = ByteUtils.byteArrayToIntReverse(data,9+ IMEI_BYTE_COUNT,4);
            logger.info("反向流量值：" + fanflowData);
            if(fanflowData > zhengflowData){
                flowData = fanflowData;
            }
            else{
                flowData = zhengflowData;
            }
            logger.info("流量值：" + flowData);
            //Battery voltage  电池电压;
            bv = ByteUtils.byteArrayToShortReverse(data,15+ IMEI_BYTE_COUNT);
            if(bv == 0 ) {
                logger.info("电池电压：0 V" );
            }
            else{
                logger.info("电池电压：" + new BigDecimal(bv).divide(new BigDecimal(100),2,RoundingMode.HALF_UP));
            }
            //rssi  信号强度;
            int rssi = ByteUtils.byteToInt(data[17+ IMEI_BYTE_COUNT]);
            logger.info("信号强度：" + rssi);
            //SNR 信噪比
            int snr = ByteUtils.byteToInt(data[18+ IMEI_BYTE_COUNT]);
            logger.info("信号比：" + snr);


        }
        else{
            logger.info("信息格式不对，不处理：" + hexStr);
            return;
        }

        MqttDeviceCurrentDto mqttDeviceCurrentDto = new MqttDeviceCurrentDto();
        mqttDeviceCurrentDto.setTime(System.currentTimeMillis());
        mqttDeviceCurrentDto.setMethod("thing.event.property.post");

        JSONObject paramJson = new JSONObject();

        logger.info("流量值：" + flowData);
        mqttDeviceCurrentDto.setDeviceCode(DEVICE_CODE_PREFIX + "_" + imei);
        paramJson.put("cumulative_flow",new BigDecimal(String.valueOf(flowData)).divide(new BigDecimal(1000),2,RoundingMode.HALF_UP));
        paramJson.put("battery_status", new BigDecimal(String.valueOf(bv)).divide(new BigDecimal(100),2,RoundingMode.HALF_UP));

        mqttDeviceCurrentDto.setParams(paramJson);

        logger.info("解析结果：" + JSONObject.toJSONString(mqttDeviceCurrentDto));

        //发送解析结果到物联网平台mqtt
        udpServerHandler.mqttSendGateway.sendToMqtt(udpServerHandler.deviceTransferService.getIotPlatPropertyTopicV1(DEVICE_TYPE), JSONObject.toJSONString(mqttDeviceCurrentDto));

        logger.info("发送mqtt完成：TOPIC:" + udpServerHandler.deviceTransferService.getIotPlatPropertyTopicV1(DEVICE_TYPE) +"  PAYLOAD:"+ JSONObject.toJSONString(mqttDeviceCurrentDto));
    }

    /**
     * 历史累计流量
     * @param data
     */
    private void decodeCommand03(byte[] data){
        String hexStr = ByteUtils.byteArrayToHexString(data);
        if(data.length != 12 + IMEI_BYTE_COUNT){
            logger.info("信息格式不对，不处理：" + hexStr);
            return;
        }
    }

}
